﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace MindBreaker.GameObjects
{
    public class GameObject : DrawableGameComponent
    {
        private static int GAMEOBJECT_FRAMES_COLLISIONLOCK = 1;

        // Class properties
        private SpriteBatch spriteBatch;
        private float _posX;
        private float _posY;
        private int _width;
        private int _height;
        private String _textureKey;
        private Texture2D _texture;
        private BoundingBox _bbox;
        private Boolean _died;
        private int _lockCollision;
        public int _lockCollisionSecurity;


        /*****************/
        /** CONSTRUCTOR **/
        /*****************/

        public GameObject(Game game, String texture, int posX, int posY)
            : base(game)
        {
            // Load the object texture
            InitVars(game, texture, posX, posY);
        }

        public void InitVars(Game game, String texture, int posX, int posY)
        {
            this.TextureKey = texture;
            // Position de l'objet
            this.PosX = posX;
            this.PosY = posY;
            this.Died = false;

            //Ajout de la boundingbox courante
            this.Bbox = this.createBoundingBox();
            this.LockCollision = 0;
            this.LockCollisionSecurity = 0;

            // Ajout au jeu courant
            this.DrawOrder = 5;
            this.Game.Components.Add(this);
        }

        public virtual int collisionWith(GameObject obj)
        {
            float centerX = this.getCenterX();
            float centerY = this.getCenterY();
            if (this.Bbox.Intersects(obj.Bbox) && this.LockCollision == 0) {
                Console.WriteLine("Collision détectée");
                // Mise en place du blocage des collisions
                this.LockCollision = GAMEOBJECT_FRAMES_COLLISIONLOCK;
                obj.LockCollision = (obj is BottomBar) ? 20 : GAMEOBJECT_FRAMES_COLLISIONLOCK;
                // Ajout d'une securité pour eviter les blocages
                if (centerX >= obj.Bbox.Min.X && centerX <= obj.Bbox.Max.X) {
                    if (centerY < obj.Bbox.Min.Y) {
                        return -1;
                    } else if (centerY > obj.Bbox.Max.Y) {
                        return -2;
                    } else {
                        return 3;
                    }
                } else {
                    if (centerX < obj.Bbox.Min.X) {
                        return 1;
                    } else if (centerX > obj.Bbox.Max.X) {
                        return 2;
                    } else {
                        return 3;
                    }
                }
            }
            return 0;
        }

        public float getCenterX()
        {
            return this.PosX + this.Width / 2;
        }

        public float getCenterY()
        {
            return this.PosY + this.Height / 2;
        }

        private BoundingBox createBoundingBox()
        {
            Vector3 upperLeftCorner = new Vector3(this.PosX, this.PosY, 0);
            Vector3 bottomRightCorner = new Vector3(this.PosX + this.Width, this.PosY + this.Height, 0);
            return new BoundingBox(upperLeftCorner, bottomRightCorner);
        }

        /***************/
        /** GAME LOOP **/
        /***************/

        public override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Default load
            TextureManager.getInstance(this.Game).loadSprites(@"images\gameComponents");

            this.spriteBatch = new SpriteBatch(GraphicsDevice);
            this.Texture = TextureManager.getInstance(this.Game).getTexture(this.TextureKey);
            this.Width = this.Texture.Width;
            this.Height = this.Texture.Height;
            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            this.Bbox = this.createBoundingBox();
            base.Update(gameTime);
        }


        public override void Draw(GameTime gameTime)
        {
            this.spriteBatch.Begin();
            this.spriteBatch.Draw(this.Texture, new Rectangle((int)this.PosX, (int) this.PosY, this.Width, this.Height), Color.White);
            this.spriteBatch.End();
            base.Draw(gameTime);
        }


        public virtual void DestroyGameObject()
        {
            this.Died = true;
            this.Game.Components.Remove(this);
        }

        // Properties access

        public float PosX
        {
            get { return _posX; }
            set { _posX = value; }
        }

        public float PosY
        {
            get { return _posY; }
            set { _posY = value; }
        }

        // Size
        public int Width
        {
            get { return _width; }
            set { _width = value; }
        }

        public int Height
        {
            get { return _height; }
            set { _height = value; }
        }

        protected String TextureKey
        {
            get { return this._textureKey; }
            set { this._textureKey = value; }
        }

        public Texture2D Texture
        {
            get { return _texture; }
            set { _texture = value; }
        }

        public BoundingBox Bbox
        {
            get { return _bbox; }
            set { _bbox = value; }
        }

        public Boolean Died
        {
            get { return _died; }
            set { _died = value; }
        }

        public int LockCollision
        {
            get { return _lockCollision; }
            set { this._lockCollision = value; }
        }

        public int LockCollisionSecurity
        {
            get { return _lockCollisionSecurity; }
            set { this._lockCollisionSecurity = value; }
        }
    }
}
